

#import "RenRenManager.h"
#import "AdapterHelp.h"
#import "JSON.h"
#import <CommonCrypto/CommonDigest.h>
#import "Model.h"

static NSString* kStringBoundary = @"3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3";
static const int kGeneralErrorCode = 10000;
static const NSTimeInterval kTimeoutInterval = 60.0;

@implementation RenRenManager

@synthesize _sessionKey;
@synthesize _call_back;
@synthesize _expirationDate;
@synthesize secret;
@synthesize sessionURL;
@synthesize restServerURL;
@synthesize connection;
@synthesize responseText;
@synthesize _result;

static RenRenManager *renrenManager = nil;



+(id)instance
{
        if (nil==renrenManager) {
            renrenManager =[[RenRenManager alloc]initWithDefault];
               }
        return renrenManager;
}

-(id)initWithDefault
{
        self = [super init];
        if (self) {
            self.appKey = @"21ff8a5b25354cc184210621e6bf9d22";
            self.appSecret = @"932b123814d04484a0576d087626415e";
            self.VERIFY_URL = @"http://graph.renren.com/oauth/authorize";
            self.sessionURL = @"https://graph.renren.com/renren_api/session_key";
            self._call_back = @"http://widget.renren.com/callback.html";
            self.restServerURL = @"http://api.renren.com/restserver.do";
            mark = FALSE;
            
            _permissions = [[NSArray arrayWithObjects:@"photo_upload publish_feed status_update operate_like read_user_feed",nil] retain];            
    
       }
    return self;
}
-(BOOL)VerifyRequest:(NSURLRequest *)request
{
    NSURL *url = request.URL;
    NSString *query = [url fragment];
	if (!query) {
		query = [url query];
	}
    AdapterHelp *adapter =[AdapterHelp new];
	NSDictionary *params = [adapter parseURLParams:query];
	self.tokenKey = [params valueForKey:@"access_token"];
    NSString *expires =[params valueForKey:@"expires_in"];
    if (expires != nil) {
        int expTime = [expires intValue];
        if (expTime == 0) {
            self._expirationDate = [NSDate distantFuture];
        }
        else
        {
            self._expirationDate = [NSDate dateWithTimeIntervalSinceNow:expTime];
        }
        
    }
    
	NSString *q = [url absoluteString];
	NSString* isOk=[q hasPrefix:self._call_back]?@"yes":@"no";
	if([isOk isEqualToString:@"yes"]&&self.tokenKey) {
		//NSLog(@"Loging Succeed:%@",self.tokenKey);
        self._sessionKey = [self getSessionKeyByToken:self.tokenKey];
        self.secret = [self getSecretKeyByToken:self.tokenKey];
        [self createUserSessionInfo];
        [adapter release];
        return NO;
	}
  
   
    [adapter release];
    return YES;

}

- (NSURLRequest*) getURLRequest
{
    NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                   self.appKey, @"client_id",
                                   @"token", @"response_type",
                                   self._call_back, @"redirect_uri",
                                   @"touch", @"display",
                                   nil];
    if (_permissions != nil) {
        NSString* scope = [_permissions componentsJoinedByString:@","];
        [params setValue:scope forKey:@"scope"];
        
    }
    NSURL* url = [self generateURL:self.VERIFY_URL params:params];
    
    return [NSURLRequest requestWithURL:url];



}

- (NSURL*)generateURL:(NSString*)baseURL params:(NSDictionary*)params {
    if (params) {
        NSMutableArray* pairs = [NSMutableArray array];
        for (NSString* key in params.keyEnumerator) {
            NSString* value = [params objectForKey:key];
            NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                                      NULL, /* allocator */
                                      (CFStringRef)value,
                                      NULL, /* charactersToLeaveUnescaped */
                                      (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                    kCFStringEncodingUTF8);
            
            [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, escaped_value]];
            [escaped_value release];
        }
        
        NSString* query = [pairs componentsJoinedByString:@"&"];
        NSString* url = [NSString stringWithFormat:@"%@?%@", baseURL, query];
        return [NSURL URLWithString:url];
    } else {
        return [NSURL URLWithString:baseURL];
    }
}


/**
 * 保存用户用oauth登录后的信息
 */
-(void)createUserSessionInfo{
    NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];	
    if (self.tokenKey) {
        [defaults setObject:self.tokenKey forKey:@"access_Token"];
    }
	if (self._expirationDate) {
		[defaults setObject:self._expirationDate forKey:@"expiration_Date"];
	}	
    if (self._sessionKey) {
        [defaults setObject:self._sessionKey forKey:@"session_Key"];
        [defaults setObject:self.secret forKey:@"secret_Key"];
    }
	
    [defaults synchronize];	
}

/**
 * 删除本地保存的用户 oauth信息 
 */
-(void)delUserSessionInfo{
	NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    [defaults removeObjectForKey:@"access_Token"];
	[defaults removeObjectForKey:@"secret_Key"];
	[defaults removeObjectForKey:@"session_Key"];
	[defaults removeObjectForKey:@"expiration_Date"];
	NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
	NSArray* graphCookies = [cookies cookiesForURL:
                             [NSURL URLWithString:@"http://graph.renren.com"]];
	
	for (NSHTTPCookie* cookie in graphCookies) {
		[cookies deleteCookie:cookie];
	}
	NSArray* widgetCookies = [cookies cookiesForURL:
                              [NSURL URLWithString:@"http://widget.renren.com"]];
	
	for (NSHTTPCookie* cookie in widgetCookies) {
		[cookies deleteCookie:cookie];
	}
	[defaults synchronize];
}



-(NSString *)getSecretKeyByToken:(NSString *) token{
	NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
								   token, @"oauth_token",
								   nil];
    NSURL* url = [self generateURL:self.sessionURL params:params];
	NSData *data=[NSData dataWithContentsOfURL:url];
	NSString* responseString = [[[NSString alloc] initWithData:data
													  encoding:NSUTF8StringEncoding]
								autorelease];
	SBJSON *jsonParser = [[SBJSON new] autorelease];
	id result = [jsonParser objectWithString:responseString];
    
	if ([result isKindOfClass:[NSDictionary class]]) {
		NSString* secretkey=[[result objectForKey:@"renren_token"] objectForKey:@"session_secret"];
		return secretkey;
	}    
    else
    {
        return nil;
    }
    
}


-(NSString *)getSessionKeyByToken:(NSString *) token{
	NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
								   token, @"oauth_token",
								   nil];
    NSURL* url = [self generateURL:self.sessionURL params:params];
	NSData *data=[NSData dataWithContentsOfURL:url];
	NSString* responseString = [[[NSString alloc] initWithData:data
													  encoding:NSUTF8StringEncoding]
								autorelease];
	SBJSON *jsonParser = [[SBJSON new] autorelease];
	id result = [jsonParser objectWithString:responseString];
    
	if ([result isKindOfClass:[NSDictionary class]]) {
		NSString* sessionkey=[[result objectForKey:@"renren_token"] objectForKey:@"session_key"];
		return sessionkey;
	}    
    else
    {
        return nil;
    }
}


- (NSString*)md5HexDigest:(NSString*)input {
	const char* str = [input UTF8String];
	unsigned char result[CC_MD5_DIGEST_LENGTH];
	CC_MD5(str, strlen(str), result);
	
	return [NSString stringWithFormat:
			@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
			result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
			result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
			];
}

- (NSString*)generateSig:(NSMutableDictionary*)_params {
	NSMutableString* joined = [NSMutableString string]; 
	NSArray* keys = [_params.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
	for (id obj in [keys objectEnumerator]) {
		id value = [_params valueForKey:obj];
		if ([value isKindOfClass:[NSString class]]) {
			[joined appendString:obj];
			[joined appendString:@"="];
			[joined appendString:value];
		}
	}
	[joined appendString:self.secret];
	return [self md5HexDigest:joined];
}

- (NSString*)generateCallId {
	return [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
}

-(BOOL)isSessionValid{
	NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
	if (defaults) {
		self.tokenKey=[defaults objectForKey:@"access_Token"];
		self._expirationDate=[defaults objectForKey:@"expiration_Date"];
		self._sessionKey=[defaults objectForKey:@"session_Key"];
		self.secret=[defaults objectForKey:@"secret_Key"];
	}
    return (self.tokenKey != nil && self._expirationDate != nil&& self._sessionKey!=nil
			&& NSOrderedDescending == [self._expirationDate compare:[NSDate date]]);
	
}

-(BOOL)isKindOfUIImage:(NSMutableDictionary *)params{
    NSString *iskind=nil;	
    for (NSString *key in [params keyEnumerator]) {
        if ([key isEqualToString:@"upload"]) {
            iskind=key;
            break;
        }
	}
	return iskind!=nil;	
}

- (NSString*)encodeString:(NSString*)actionString urlEncode:(NSStringEncoding)enc {
	NSMutableString *escaped = [NSMutableString string];
	[escaped setString:[actionString stringByAddingPercentEscapesUsingEncoding:enc]];
	
	[escaped replaceOccurrencesOfString:@"&" withString:@"%26" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"+" withString:@"%2B" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"," withString:@"%2C" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@";" withString:@"%3B" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"=" withString:@"%3D" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"?" withString:@"%3F" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"@" withString:@"%40" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@" " withString:@"+" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"\t" withString:@"%09" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"#" withString:@"%23" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"<" withString:@"%3C" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@">" withString:@"%3E" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"\"" withString:@"%22" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	[escaped replaceOccurrencesOfString:@"\n" withString:@"%0A" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [escaped length])];
	return escaped;
}

- (NSMutableData *)generatePostBody:(NSMutableDictionary*) params {
	NSMutableData *body = [NSMutableData data];
	NSString *endLine = [NSString stringWithFormat:@"\r\n--%@\r\n", kStringBoundary];
	NSMutableArray *pairs = [NSMutableArray array];
    if ([self isKindOfUIImage:params]) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", kStringBoundary]
                          dataUsingEncoding:NSUTF8StringEncoding]];
        for(NSString *key in [params keyEnumerator]){
            if ([key isEqualToString:@"upload"]) {
                continue;
            }
            [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name = \"%@\"\r\n\r\n", key]
                              dataUsingEncoding:NSUTF8StringEncoding]];
            [body appendData:[[params valueForKey:key] dataUsingEncoding:NSUTF8StringEncoding]];
            
            [body appendData:[endLine dataUsingEncoding:NSUTF8StringEncoding]];
        }
        NSData *_dataParam=[params valueForKey:@"upload"];
        NSData* imageData = UIImagePNGRepresentation((UIImage*)_dataParam);
        [body appendData:[[NSString
                           stringWithFormat:@"Content-Disposition: form-data; name=\"upload\";filename=no.jpg"]
                          dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[endLine dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString
                           stringWithString:@"Content-Type:image/jpeg\r\n\r\n"]
                          dataUsingEncoding:NSUTF8StringEncoding]];  
        [body appendData:imageData];
        [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", kStringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    }else {
        for (NSString* key  in [params keyEnumerator]) {
            NSString* value = [params objectForKey:key];
            NSString* value_str = [self encodeString:value urlEncode:NSUTF8StringEncoding];
            [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, value_str]];
        }
        NSString* params = [pairs componentsJoinedByString:@"&"];
        [body appendData:[params dataUsingEncoding:NSUTF8StringEncoding]];
    }
    return body;
}

- (void)requestWithParams:(NSMutableDictionary *)params{
    
    if ([params objectForKey:@"method"] == nil) {
      //  NSLog(@"API Method must be specified");
        return ;
    }
	if ([self isSessionValid]) {
		[params setObject:self._sessionKey forKey:@"session_key"];
    }else {
		//[self delUserSessionInfo];
	//	NSLog(@"session not valid");
		return ;
	}
	
	[params setObject:[self generateCallId] forKey:@"call_id"];//增加键与值
	[params setObject:self.appKey forKey:@"api_key"];	
	[params setObject:@"1.0" forKey:@"v"];
	[params setObject:@"json" forKey:@"format"];
	[params setObject:@"1" forKey:@"xn_ss"];
	
	NSString *sig=[self generateSig:params];
	[params setObject:sig forKey:@"sig"];
    
    NSMutableURLRequest* urlRequest =
    [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.restServerURL]
                            cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                        timeoutInterval:kTimeoutInterval];
    
	[urlRequest setHTTPMethod:@"POST"];
	if ([self isKindOfUIImage:params]) {
		NSString* contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kStringBoundary];
		[urlRequest setValue:contentType forHTTPHeaderField:@"Content-Type"];
	}
	[urlRequest setHTTPBody:[self generatePostBody:params]];

    self.connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
    
    return;
    

}

- (id)formError:(NSInteger)code userInfo:(NSDictionary *) errorData {
    
    return [NSError errorWithDomain:@"renrenErrDomain" code:code userInfo:errorData];
    
}


- (id)parseJsonResponse:(NSData *)data error:(NSError **)error {
    
    NSString* responseString = [[[NSString alloc] initWithData:data
                                                      encoding:NSUTF8StringEncoding]
                                autorelease];
    SBJSON *jsonParser = [[SBJSON new] autorelease];
    if ([responseString isEqualToString:@"true"]) {
        return [NSDictionary dictionaryWithObject:@"true" forKey:@"result"];
    } else if ([responseString isEqualToString:@"false"]) {
        if (error != nil) {
            *error = [self formError:kGeneralErrorCode
                            userInfo:[NSDictionary
                                      dictionaryWithObject:@"This operation can not be completed"
                                      forKey:@"error_msg"]];
        }
        return nil;
    }
    
   // NSLog(@"=====%@",responseString);
    id result = [jsonParser objectWithString:responseString];
    
    if (![result isKindOfClass:[NSArray class]]) {
        if ([result objectForKey:@"error"] != nil) {
            if (error != nil) {
                *error = [self formError:kGeneralErrorCode
                                userInfo:result];
            }
            return nil;
        }
        
        if ([result objectForKey:@"error_code"] != nil) {
            if (error != nil) {
                *error = [self formError:[[result objectForKey:@"error_code"] intValue] userInfo:result];
            }
            return nil;
        }
        
        if ([result objectForKey:@"error_msg"] != nil) {
            if (error != nil) {
                *error = [self formError:kGeneralErrorCode userInfo:result];
            }
        }
        
        if ([result objectForKey:@"error_reason"] != nil) {
            if (error != nil) {
                *error = [self formError:kGeneralErrorCode userInfo:result];
            }
        }
    }
    
    return result;
    
}

-(NSMutableArray *) getStatus
{
    
    
    NSMutableDictionary * params2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                             @"feed.get",@"method",
                                             @"20,21",@"type",nil];
    
    [self requestWithParams:params2]; 
    
    while (!mark) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
    
    
    NSMutableArray * statusArray = [NSMutableArray arrayWithCapacity:30];
    NSError** a;
    if (self.responseText) {
    
        self._result=[self parseJsonResponse:self.responseText error:a];
        
        if ([self._result isKindOfClass:[NSArray class]]) {
            
            NSInteger count = [self._result count];
            
            for (int i=0; i<count; i++) {
                Status * status = [[Status alloc] init];
                User * user = [[User alloc] init];
                NSDictionary * dt =[self._result objectAtIndex:i]; 
                user.screen_name= [ dt valueForKey:@"name"];
                user.profile_image_url = [ dt valueForKey:@"headurl"];
                status.user = user;
                status.prefix = [dt valueForKey:@"prefix"];
                status.title = [dt valueForKey:@"title"];
                status.text = [dt valueForKey:@"description"];
                status.message = [dt valueForKey:@"message"];
                status.created_at =[ dt valueForKey:@"update_time"];
                
                NSString *place = [[dt valueForKey:@"place"] valueForKey:@"address"];
                status.source = place?place:@"未知地点";  
                [statusArray addObject:status];
            }
            
            return statusArray; 
        }
    
    
    }
    
    
    return nil;
}



// NSURLConnectionDelegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    self.responseText = [[NSMutableData alloc] init];
    

}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.responseText appendData:data];
}

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse*)cachedResponse {
    return nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    
    
    mark =TRUE;
    [self.connection release];
    self.connection = nil;
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    
    
   // NSLog(@"ConnectDidFail");
    [self.responseText release];
    self.responseText = nil;
    [self.connection release];
    self.connection = nil;
}



@end

























